package com.charging.business.service;

import com.charging.business.config.MinFeeManager;
import com.charging.business.enums.Issuer;
import com.charging.business.exception.CustomizeException;
import com.charging.business.jin.EnStations;
import com.charging.business.jin.JinOnLineRequest;
import com.charging.business.qin.Db3FileUtils;
import com.charging.business.utils.RosterUtils;
import com.charging.business.utils.PayUtil;
import com.charging.business.vo.FeeExCalcRequest;
import com.charging.business.vo.FeeExCalcResponse;
import com.charging.business.vo.obj.MiniFeeInfo;
import com.charging.business.vo.obj.OnlineFeeInfo;
import com.charging.business.vo.obj.SplitProvinceMini;
import com.charging.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author JerryLu
 * @date 2024/11/30 17:03
 * @description 无通行介质计费
 */
@Component
public class FeeNoCardHandle {
    private static final Logger logger = LoggerFactory.getLogger(FeeNoCardHandle.class);

    public static String enStationId = "";

    private static boolean beWantMinFee = false;

    @Autowired
    private MinFeeManager minFeeManager;

    @Autowired
    private Db3FileUtils db3FileUtils;

    @Autowired
    private RosterUtils rosterUtils;

    public FeeExCalcResponse run(FeeExCalcRequest request, FeeExCalcResponse response) throws Exception {
        // 1、在线获取入口信息
        response = this.specialFee(request, response);
        long s1 = System.currentTimeMillis();
        if (request.getEnStationId().isEmpty() || request.getEnStationHex().isEmpty()) {
            return response;
        }
        long s2 = System.currentTimeMillis();
        logger.info("在线获取入口信息完成,耗时{}毫秒", s2 - s1);

        // 2、最小费额计费
        long s3 = System.currentTimeMillis();
        response = this.getMinFee(request, response);
        logger.info("无通行介质最小费额算费结束,耗时{}毫秒", s3 - s2);

//        response = this.compare(request, response);
        return response;
    }

    /**
     * 在线获取入口信息
     *
     * @param request
     * @throws CustomizeException
     */
    public FeeExCalcResponse specialFee(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        List<EnStations> enStationsResP = new ArrayList<>();
        long s1 = System.currentTimeMillis();
        if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
            JinOnLineRequest onLineRes = new JinOnLineRequest();
            onLineRes.setMediaId(request.getMediaNo());
            onLineRes.setExStationId(request.getExStationHex() + "|" + request.getExStationId());
            onLineRes.setExTime(request.getExTime());
            onLineRes.setVehicleId(request.getVehicleId());
            onLineRes.setVehicleType(request.getExVehicleType());
            onLineRes.setVehicleClass(request.getVehicleClass());
            if (request.getPayType() != null) {
                onLineRes.setPayType(request.getPayType());
            }
            onLineRes.setFeeType(2);
            onLineRes.setSecondConfirm(0);
            onLineRes.setAxleCount(request.getExAxleCount());
            onLineRes.setEnTime(request.getEnTime());
            onLineRes.setIsETC(request.getIsDiscount());
            onLineRes.setMediaType(request.getMediaType());
            onLineRes.setEnTollLaneId(request.getEnTollLaneId());
            onLineRes.setExTollLaneId(request.getExTollLaneId());
            onLineRes.setIsMultiProv(1);
            onLineRes.setVehicleUserType(request.getVehicleUserType());
            onLineRes.setIssuerId(request.getIssuerId());
            onLineRes.setReqVersion(Long.parseLong(DateUtils.dateTime()));
            onLineRes.setVehicleSign(request.getVehicleSign());

            enStationsResP = rosterUtils.getJinExOnlineFeeForNoCard(onLineRes, request);
        }
//        else {
//            QinOnLineRequest onLineRes = new QinOnLineRequest();
//            onLineRes.setRequestId(IdUtils.fastSimpleUUID());
////            onLineRes.setSplitProvince(IdUtils.fastSimpleUUID());
//            onLineRes.setRequestType(11);
//            if (request.obuEf04Model != null && request.obuEf04Model.provCount != 0) {
//                onLineRes.setMultiProvince(request.obuEf04Model.provCount > 1 ? 1 : 0);
//            } else {
//                onLineRes.setMultiProvince(9);
//            }
//            onLineRes.setPassId(request.getPassId());
//            onLineRes.setMediaType(request.getMediaType());
//            onLineRes.setMediaNo(request.getMediaNo());
//            onLineRes.setIssuerId(request.getIssuerId());
////            onLineRes.setIssuerId(request.card0015Model.getIssuerId6());
//            onLineRes.setIsDiscount(request.getIsDiscount());
//            onLineRes.setValidShortFee(request.getValidShortFee() == null || request.getValidShortFee() == 1 ? 1 : 2);
//            onLineRes.setEnLaneId(request.getEnTollLaneId());
//            onLineRes.setEnTime(request.getEnTime());
//            onLineRes.setVehicleId(request.getVehicleId());
//            onLineRes.setExLaneId(request.getExTollLaneId());
//            onLineRes.setExTime(request.getExTime());
//            onLineRes.setVehicleType(request.getExVehicleType());
//            onLineRes.setVehicleUserType(request.getVehicleUserType());
//            onLineRes.setAxleCount(request.getExAxleCount());
//            spececReponse = rosterUtils.getQinExOnlineFeeForNoCard(onLineRes, response);
//        }

        // 返回入口信息重新计费。不走当前流程。走单刷卡或者CPC。
        long s2 = System.currentTimeMillis();
        logger.info("在线获取入口信息完成,耗时{}毫秒", s2 - s1);
        response.setEnStationInfo(enStationsResP);
        response.setExitFeeType(250);
        response.setRateVersion(null);
        response.setSpcRateVersion(null);

        return response;
    }

    /**
     * 兜底计费，分省合并
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public FeeExCalcResponse getMinFee(FeeExCalcRequest request, FeeExCalcResponse response) throws Exception {
        // 获取最小费额版本号
        boolean bETC = true;
        try {
            MiniFeeInfo miniFeeInfo = new MiniFeeInfo();
            String minVersion = minFeeManager.getCurrentVersion();
            miniFeeInfo.spcRateVersion = minVersion;
            ArrayList<SplitProvinceMini> minProvinces = new ArrayList<>();
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                //陕西
                try {
                    db3FileUtils.loadDb3File(enStationId, request.getExStationId(), request.getExVehicleType());
                    minProvinces = minFeeManager.getMinFee(bETC, enStationId, request.getExStationId(), request.getExVehicleType());
                } catch (Exception e) {
                    throw new CustomizeException("获取最小费额失败");
                }
            } else {
                minProvinces = rosterUtils.getMiniFee(request.getEnStationId(), request.getExStationId(), request.getExVehicleType(), request.getExAxleCount(), bETC);
            }
            if (minProvinces.isEmpty()) {
                throw new CustomizeException("获取兜底计费失败：查询不到对应的出口计费信息");
            }

            // 汇总最小费额信息
            for (SplitProvinceMini prov : minProvinces) {
                miniFeeInfo.zMinPayFee += prov.ziMinPayFee;
                miniFeeInfo.zMinFee += prov.ziMinFee;
                miniFeeInfo.calMinFeeFee += prov.calMinFeeFee;
                miniFeeInfo.calMinFeeFee95 += prov.calMinFeeFee95;
                miniFeeInfo.calMinFeeMileage += prov.calMinFeeMileage;
            }
            miniFeeInfo.splitProvince = minProvinces;
            //陕西合并分省信息
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                miniFeeInfo.merge();
            }

            response.setSpcRateVersion(minVersion);
            response.setRateVersion(miniFeeInfo.splitProvince.get(miniFeeInfo.splitProvince.size() - 1).rateVersion);
            response.setMiniFeeInfo(miniFeeInfo);
            response.setExitFeeType(6);
            logger.info("最小费额计费结束：通行省份个数：{}，总应收：{}元，总实收：{}元，95折总实收：{}元，总里程：{}公里，费额费率版本号：{}", miniFeeInfo.splitProvince.size(), PayUtil.convertFee(miniFeeInfo.calMinFeeFee), PayUtil.convertFee(miniFeeInfo.zMinFee), PayUtil.convertFee(miniFeeInfo.calMinFeeFee95), PayUtil.convertMileage(miniFeeInfo.calMinFeeMileage), minVersion);
        } catch (CustomizeException e) {
            throw new CustomizeException(!e.getMessage().isEmpty() ? e.getMessage() : "获取兜底计费异常");
        }
        return response;
    }

    public FeeExCalcResponse compare(FeeExCalcRequest request, FeeExCalcResponse response) throws Exception {
        OnlineFeeInfo onlineFeeInfo = response.getOnlineFeeInfo();
        int spFee = 0;
        int minFee = 0;
        int spMileage = 0;
        int minMileage = 0;
        //在线计费应收金额
        spFee = onlineFeeInfo.getPayFee();
        //最小费额应收金额
        minFee = response.getMiniFeeInfo().calMinFeeFee;
        //在线计费总里程
        spMileage = onlineFeeInfo.getFeeMileage();
        //最小费额里程
        minMileage = response.getMiniFeeInfo().calMinFeeMileage;

        //是否验证最小费额，请求参数里里带入
        if (request.getValidShortFee() == null || request.getValidShortFee() == 1) {
            if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
                //根据山西计费规则。分为客车与6轴以下货车 和6轴以上货车
                if (request.getExVehicleType() <= 4 || request.getExAxleCount() <= 6) {
                    if (spFee >= minFee * 0.9f && spFee <= minFee * 1.5f) {
                        // d)在线计费应收金额大于等于最小费额应收下限值且
                        // 在线计费应收金额小于等于最小费额应收上限值时使用在线计费金额计费
                        beWantMinFee = false;
                    } else if (spFee >= minFee * 0.9f && spFee > minFee * 1.5f && spMileage < minMileage * 1.5f) {
                        //e)在线计费应收金额大于等于最小费额应收下限值且
                        //在线计费应收金额大于最小费额应收上限值且
                        //在线计费里程小于最小费额应收里程上限值时使用在线计费金额计费
                        beWantMinFee = false;
                    } else if (spFee >= minFee * 0.9f && spFee > minFee * 1.5f && spMileage > minMileage * 1.5f) {
                        //f)在线计费应收金额大于等于最小费额应收下限值且
                        //在线计费应收金额大于最小费额应收上限值且
                        //在线计费里程大于最小费额应收里程上限值时需要监控授权是否使用在线计费金额，如果监控回控同意则使用
                        logger.info("监控授权...");
//                    beWantMinFee = false;
                    } else {
                        //g)不满足以上条件则转最小费额计费
                        beWantMinFee = true;
                    }
                } else {
                    //6轴以上货车
                    int otherProMinFee = response.miniFeeInfo.payFeeProvSumOther(); //外省兜底应收金额
                    double selfProMinFee = response.miniFeeInfo.payFeeProvSumLocal(); //本省兜底应收金额
                    // 大于18轴按18轴计算
                    int exAxleCount = request.getExAxleCount() > 18 ? 18 : request.getExAxleCount();
                    double selfProMinFee1 = selfProMinFee * (1 + (exAxleCount - 6) * 0.2f);
                    int proNum = request.obuEf04Model.provCount;//通行省份个数
                    double folowFee = (otherProMinFee + selfProMinFee1) - proNum * 50f;
                    beWantMinFee = !(spFee >= folowFee);
                }
            } else {
                //包年车辆：15-绕城包年 16-西阎包年 17-绕城西阎包年
                int vehicleUserType = request.getVehicleUserType();
                int basicAmount = 0;
                double amount = 0; //下限
                double lowAmount; //下限
                double upperAmount = minFee * 5f; //上限
                if (vehicleUserType == 15) {
                    basicAmount = 4371;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else if (vehicleUserType == 16) {
                    basicAmount = 2825;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else if (vehicleUserType == 17) {
                    basicAmount = 7196;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else {
                    lowAmount = minFee * 0.9f;
                }

                beWantMinFee = !(spFee >= lowAmount) || !(spFee <= upperAmount);
            }
        }

        if (beWantMinFee) {
            response.setExitFeeType(6);
            response.setOnlineFeeInfo(null);
        }
        return response;
    }
}
